library(brms)
library(dplyr)
library(ggplot2)
library(ggthemes)
library(kfigr)
library(knitr)
library(patchwork)
The data set was read in as is, the columns subj, arm, cond, series and no were converted to factors, the column filename was deleted. A new column was added to the dataset, patient, based on the subj prefix (‘P’ or ‘S’), with a ‘0’ coding for healthy controls, and a ‘1’ for patients.
read.csv("features.csv") %>%
mutate(filename = NULL,
patient = factor(if_else(grepl("^P",
subj),
1L,
0L)),
series = factor(series),
subj = factor(subj),
arm = factor(arm),
cond = factor(cond),
no = factor(no)) ->
drum_beats
In a first attempt to get an overview, the descriptors’ density estimates were plotted, broken down by arm and cond.
dep_vars <- names(drum_beats)[which(!(names(drum_beats) %in% c("subj",
"arm",
"cond",
"no",
"series",
"patient")))]
n_vars <- length(dep_vars)
plot_lst <- vector("list", length = n_vars)
plt_cnt <- 1
for (dv in dep_vars) {
if (plt_cnt == n_vars) {
plt_pos <- c(2, 0.5)
} else {
plt_pos <- "none"
}
if (plt_cnt %% 4 == 1) {
ylab <- "density"
} else {
ylab <- ""
}
plot_lst[[plt_cnt]] <- ggplot(drum_beats,
aes_string(x = dv,
color = "cond")) +
geom_density(na.rm = TRUE) +
scale_color_colorblind() +
ylab(ylab) +
geom_rug(alpha = 0.25) +
theme(legend.position = plt_pos) +
facet_wrap(~ arm)
plt_cnt <- plt_cnt + 1
}
print(wrap_plots(plot_lst,
ncol = 4) +
plot_annotation(
tag_levels = "A"))
Fig. 1. Descriptor densities along with raw data points (rug ticks on x axes), broken down by arm (dominant [D] vs non-dominant [ND]) and instruction condition (controlled = C, normal = N).
Several peculiarities are immediately apparent from the plots in Fig. 1:
attDur, LAT, and attFlat have very few unique data values (see rug ticks at bottom of plots)attDur, LAT, and attFlat for the reason just mentioned)The lack of any clear-cut differences in the raw data between conditions suggests that it will be hard to find any differences by modeling.
The limited number of unique values in the attack-related measures (e.g. attDur only has 35 unique values in a total of 1102 observations across all subjects, conditions, and sides; that’s only 3 percent!) suggests that rounding errors propagated through the calculations. This is probably due to very similar, i.e. highly automated, and short attack times combined with the given sampling frequency, resulting in few data points, which in course of the calculations result in the observed phenomenon. But I’m just guessing here, as I do not know anything about these descriptors and how they are calculated or interpreted. Judging by the range of values of, i.e., attDur (2.59, 9.8ms, across both sides and conditions) and a sampling frequency of 48 kHz, this leaves us at 48 * (9.8 - 2.59) = 346 points to choose beginning and end of the attack. Given the supposed highly automatized motor program used to initiate the stroke, along with the laws of physics at play here (no pun intended), it is not very surprising to see very few unique values. My limited knowledge—or rather, my ignorance of anything sound-related—aside, from a statistical standpoint these measures do not seem suited to describe any differences between the experimental conditions investigated here.
Given the very few data points in the attack phase, any descriptor derived from such a short period of time (.e.g.. attSPL) cannot be judged as being stable in the sense of being reproducible. Hence I suggest to drop all attack-derived descriptors.
# drum_beats %>%
# mutate(attDur = NULL,
# LAT = NULL,
# attSPL = NULL,
# attSC = NULL,
# attFlat = NULL,
# attSpecFlat = NULL) ->
# drum_beats
The increase in variance for the conditions N < C does not come as a surprise as I assume normal also means highly trained and thus automatized, whereas controlled involves less automatization and more ‘individualness’ both within and between subjects.
Looking at the above investigated descriptors and Danielsen et al. (2015), it seems reasonable to limit the modeling attempts to totDur, totSPL, totSC, and TC.
But Sofia wrote on 2020-07-09: “Francesco and I have discussed a bit related to descriptors and we want to concentrate on the “transient” period (although the name probably will change). Spectral Centroid (transSC) should be one, and I suggest transFlat for the other. Francesco, does that sound reasonable?"
On 2020-07-22 both Sofia and Francesco agreed upon transSC, transFlat, and transCrest as the probably most important response variables to look at.
Update:
attFlat is fixed by solving a bug in the feature extraction: now the downsampling ratio for the envelope extraction is reduced, and makes the MIRToolbox algorithm less sensitive to frames with an rms value of 0 (which returns an incorrect value of 0, since we have a geometric mean at the numerator). Now we have a larger spread which allows high values (1 = peaky envelope, 0 = smooth/flat envelope).Regarding the attack phase: I agree with the remarks regarding duration. Given the fact that we are not comparing different instruments, I wouldn’t have expected a large variation. This is not surprising if we consider that our system is changing only slightly (same rototom, same drumstick, same action, a bit different tuning across subjects): in fact, the perceived timbral differences are so small that we are in trouble guessing on the descriptors.
The sampling frequency is even lower (\(f_s = 44100\) Hz). Even if we had a higher sample rate which could reveal some discrepancies in the attack durations, we would have to prove that they are perceptually relevant.
Therefore, I am happy to discard attDur and LAT (which is obviously a log-transformed duration, only there for the sake of consistency with the literature).
I am a bit more in doubt when it comes to discarding all the attack descriptors. Even if what Michael says is true from a statistical point of view, we should still be able to discriminate timbre on short time windows due to the high temporal resolution of our hearing. Attack phase descriptors (with the same definition of attack that we are using, which is most likely not coincident with perceptual attack) are employed in Câmara et al. (2020), and the Oslo group has a paper under construction which analyzes drum sounds in a similar manner (see OsloPlots.png in the OneDrive folder).
I am worried that merely taking the overall descriptors into account would introduce a lot of unnecessary and perceptually catching information — mostly the tonal part of the signal, i.e. the drum ringing in the last part of the decay. That’s why Sofia and I are suggesting to look at what we could call “main energy” or “early decay” phase (i.e. from max peak to temporal centroid).
Would it be feasible to set up 4 different models (i.e. one for each phase), at least in the univariate version?
As for the descriptors to include: although TC is employed in Danielsen et al. (2015), the PDFs are even more similar. I would go for Dur (except attack?), SPL, SC, and one between Flat, SpecFlat or Crest.
My (informal and biased) listening tests tell me that, at least for some subjects, I hear a pattern going towards a harsher (controlled) vs smoother (normal) timbre exactly at the hit point, plus slightly less (controlled) or more pitch/amplitude fluctuation. Hopefully this could be catched by spectral centroid, specrtral/temporal flatness, or crest factor. This should be independent of SPL unless the subject misinterpreted the instructions, therefore SPL acts as a sort of control variable in our model.
There are several points that need to be considered before making a decision regarding the type of modeling to be done in this study, (1) the sample size places restrictions on the external validity; (2) data from small samples can be better modeled when regularization is in place to ‘tame’ the estimates; (3) the hierarchical structure of the data (subjects played several trials with either their dominant or non-dominant arm under two conditions) suggests a multilevel analysis of the data which would, in addition to the Bayesian regularization via priors, also results in shrinkage of the estimates; (4) given the small distribution differences between the two experimental conditions, along with the
# chunk intentionally empty
Group: Patient Healthy Control
/ \ / \
Instruction: Normal Controlled Normal Controlled
| | \ / | \
Player: 1 2 ... n 1 2 ... n
/ \
Side dominant non-dominant
/ | \ / | \
Trial 1 .. p 1 .. p
Fig. 2. The multilevel structure of a data set should be reflected in the analysis.
Will start with a simple univariate model, add predictors and interactions, then a bivariate model, and finally a quadruple-variate model and see where this leads us.
The humps in the density distributions in section Instruction Condition, and Arm Used made me curious where they might originate from. So in the following graph the density estimates of one of the descriptors, transSC, are plotted broken down by subj. and then also by cond, separately for patients and healthy subjects.
ggplot(drum_beats, aes(transSC,
color = subj,
linetype = cond)) +
geom_density(alpha = 0.1) +
scale_color_colorblind()
Fig. 3. transSC density distribution of participants, broken down by instruction condition.
It is obvious that some participants do not differ substantially between the normal and the controlled condition, whereas others do, and even markedly so. Additionally, there seems to be quite a spread of the centers of distributions across a wide range of values, suggesting very individual drum sounds.
The wide distribution of centers of mass between individuals made me want to further break down the plot.
ggplot(drum_beats, aes(transSC,
color = subj,
linetype = cond)) +
geom_density(alpha = 0.1) +
scale_color_colorblind() +
facet_wrap(~ patient)
Fig. 4. transSC density distribution of participants, broken down by instruction condition and group (patients and healthy subjects).
The above plot is interesting in that it seems to show that the four healthy subjects were more uniform than the patients in their transSC distributions and also, with the exception of S2, had very similar transSC distributions for the normal and the controlled conditions. In the patients, two had very similar distributions in both conditions (P1 and P5), whereas the two others showed differing results for the two conditions. So with regard to Sofia’s hypothesis (ch. Modeling) I’d argue, at least for transSC alone, having drummers play normal and controlled strokes would not allow subjects to tell the difference in a listening test. But maybe it would qualify as a screening test for movement disorders in drummers. Just a random thought.
While breaking it down it occurred to me that looking at individual variation (that is, between series) might also be enlightening.
ggplot(drum_beats, aes(transSC,
color = cond,
group = series)) +
geom_density(alpha = 0.1) +
scale_color_colorblind() +
facet_wrap(~ subj, nrow = 2)
Fig. 5. Density plots of individual series.
And it was! The plot in Fig. 5 made visible that P1 and P5 had consistently very low transSC values. P3 was consistent within the normal instruction condition, but had, on average, higher values, and with a lot more variation, in the controlled condition. P4 had more variation in both conditions, and higher transSC values in both; in other words, P4 was consistantly bad. (But then again: what do I know what bad is wrt transSC!)
The healthy subjects showed comparable variation and centers of mass within conditions, and all but one (S2) also across conditions.
Comparing the two rows of panels in Fig. 5 reveals that healthy subjects have more variation than the patients.
Although tempting, we probably shouldn’t get carried away and generalize to the populations of healthy drummers and ones with movement disorders, respectively.
cov_mat <- cov(drum_beats[-c(1:5, ncol(drum_beats))],
use = "pairwise.complete.obs")
kable(cov_mat, digits = 2)
| totDur | attDur | decDur | transDur | LAT | totSPL | attSPL | decSPL | transSPL | totSC | attSC | decSC | transSC | TC | totFlat | attFlat | decFlat | transFlat | totSpecFlat | attSpecFlat | decSpecFlat | transSpecFlat | totCrest | attCrest | decCrest | transCrest | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| totDur | 8580.54 | 32.18 | 7641.34 | 907.01 | 5.93 | -125.00 | -205.08 | -41.76 | -90.45 | -449.09 | -7391.47 | 1448.04 | -6574.23 | 999.35 | -0.79 | 1.26 | -2.41 | 2.57 | 1.05 | -0.17 | 1.31 | 0.12 | -90.78 | -13.10 | 27.04 | -39.39 |
| attDur | 32.18 | 1.15 | 30.22 | 0.81 | 0.23 | 0.26 | -0.66 | 0.25 | 0.43 | 8.36 | -171.34 | 47.75 | -101.81 | 2.68 | -0.02 | 0.02 | -0.02 | 0.01 | 0.01 | 0.00 | 0.01 | 0.00 | -1.26 | -0.26 | -0.03 | -0.40 |
| decDur | 7641.34 | 30.22 | 6838.06 | 773.06 | 5.66 | -108.21 | -177.56 | -36.46 | -76.60 | -325.99 | -7202.60 | 1404.24 | -5920.35 | 867.57 | -0.87 | 1.19 | -2.28 | 2.27 | 0.94 | -0.17 | 1.16 | 0.11 | -82.96 | -12.27 | 25.25 | -35.30 |
| transDur | 907.01 | 0.81 | 773.06 | 133.13 | 0.04 | -17.05 | -26.86 | -5.55 | -14.28 | -131.46 | -17.53 | -3.96 | -552.06 | 129.09 | 0.09 | 0.05 | -0.10 | 0.28 | 0.11 | 0.01 | 0.13 | 0.02 | -6.57 | -0.57 | 1.83 | -3.68 |
| LAT | 5.93 | 0.23 | 5.66 | 0.04 | 0.05 | 0.10 | -0.08 | 0.10 | 0.14 | 1.11 | -37.72 | 8.53 | -19.80 | 0.40 | 0.00 | 0.00 | -0.01 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | -0.26 | -0.05 | -0.01 | -0.08 |
| totSPL | -125.00 | 0.26 | -108.21 | -17.05 | 0.10 | 35.41 | 35.05 | 34.35 | 35.05 | -118.69 | -128.44 | -209.89 | -29.55 | -18.56 | 0.03 | 0.01 | 0.07 | -0.02 | -0.03 | 0.00 | -0.04 | -0.01 | -0.25 | 0.01 | -0.77 | 0.40 |
| attSPL | -205.08 | -0.66 | -177.56 | -26.86 | -0.08 | 35.05 | 37.49 | 33.06 | 34.36 | -119.69 | 94.87 | -274.74 | 122.55 | -30.48 | 0.04 | -0.03 | 0.10 | -0.06 | -0.05 | 0.00 | -0.06 | -0.01 | 2.08 | 0.38 | -0.61 | 1.09 |
| decSPL | -41.76 | 0.25 | -36.46 | -5.55 | 0.10 | 34.35 | 33.06 | 34.70 | 34.18 | -130.19 | -122.66 | -211.16 | -48.42 | -5.80 | 0.03 | 0.02 | 0.04 | 0.01 | -0.02 | 0.00 | -0.03 | 0.00 | -1.13 | -0.10 | -0.53 | 0.06 |
| transSPL | -90.45 | 0.43 | -76.60 | -14.28 | 0.14 | 35.05 | 34.36 | 34.18 | 34.88 | -119.50 | -177.76 | -202.01 | -60.17 | -15.25 | 0.02 | 0.02 | 0.06 | -0.01 | -0.02 | -0.01 | -0.03 | -0.01 | -0.64 | -0.06 | -0.63 | 0.24 |
| totSC | -449.09 | 8.36 | -325.99 | -131.46 | 1.11 | -118.69 | -119.69 | -130.19 | -119.50 | 5907.01 | 1707.28 | 8098.86 | 1471.12 | -94.91 | -0.64 | 0.24 | -0.75 | -0.58 | 0.58 | 0.17 | 0.72 | 0.12 | 9.18 | -3.27 | 1.29 | 5.57 |
| attSC | -7391.47 | -171.34 | -7202.60 | -17.53 | -37.72 | -128.44 | 94.87 | -122.66 | -177.76 | 1707.28 | 62304.01 | -5496.05 | 21851.87 | -301.21 | 5.33 | -5.54 | 6.07 | -4.17 | -1.74 | 1.92 | -2.23 | -0.10 | 314.17 | 49.56 | -7.49 | 83.34 |
| decSC | 1448.04 | 47.75 | 1404.24 | -3.96 | 8.53 | -209.89 | -274.74 | -211.16 | -202.01 | 8098.86 | -5496.05 | 13980.47 | -3473.23 | 115.29 | -1.76 | 1.22 | -2.51 | 0.47 | 1.42 | 0.13 | 1.80 | 0.24 | -53.07 | -16.77 | -0.43 | -13.80 |
| transSC | -6574.23 | -101.81 | -5920.35 | -552.06 | -19.80 | -29.55 | 122.55 | -48.42 | -60.17 | 1471.12 | 21851.87 | -3473.23 | 16789.09 | -752.03 | 1.85 | -2.86 | 2.51 | -3.28 | -1.54 | 0.35 | -1.93 | -0.14 | 171.49 | 29.11 | 4.67 | 61.51 |
| TC | 999.35 | 2.68 | 867.57 | 129.09 | 0.40 | -18.56 | -30.48 | -5.80 | -15.25 | -94.91 | -301.21 | 115.29 | -752.03 | 183.60 | 0.06 | 0.02 | -0.16 | 0.32 | 0.14 | 0.00 | 0.17 | 0.02 | -8.94 | -1.05 | 1.79 | -4.55 |
| totFlat | -0.79 | -0.02 | -0.87 | 0.09 | 0.00 | 0.03 | 0.04 | 0.03 | 0.02 | -0.64 | 5.33 | -1.76 | 1.85 | 0.06 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.04 | 0.01 | -0.01 | 0.01 |
| attFlat | 1.26 | 0.02 | 1.19 | 0.05 | 0.00 | 0.01 | -0.03 | 0.02 | 0.02 | 0.24 | -5.54 | 1.22 | -2.86 | 0.02 | 0.00 | 0.01 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | -0.05 | -0.01 | 0.00 | -0.01 |
| decFlat | -2.41 | -0.02 | -2.28 | -0.10 | -0.01 | 0.07 | 0.10 | 0.04 | 0.06 | -0.75 | 6.07 | -2.51 | 2.51 | -0.16 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.06 | 0.01 | -0.01 | 0.02 |
| transFlat | 2.57 | 0.01 | 2.27 | 0.28 | 0.00 | -0.02 | -0.06 | 0.01 | -0.01 | -0.58 | -4.17 | 0.47 | -3.28 | 0.32 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | -0.05 | -0.01 | 0.00 | -0.02 |
| totSpecFlat | 1.05 | 0.01 | 0.94 | 0.11 | 0.00 | -0.03 | -0.05 | -0.02 | -0.02 | 0.58 | -1.74 | 1.42 | -1.54 | 0.14 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | -0.02 | 0.00 | 0.00 | -0.01 |
| attSpecFlat | -0.17 | 0.00 | -0.17 | 0.01 | 0.00 | 0.00 | 0.00 | 0.00 | -0.01 | 0.17 | 1.92 | 0.13 | 0.35 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.01 | 0.00 | 0.00 | 0.00 |
| decSpecFlat | 1.31 | 0.01 | 1.16 | 0.13 | 0.00 | -0.04 | -0.06 | -0.03 | -0.03 | 0.72 | -2.23 | 1.80 | -1.93 | 0.17 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | -0.02 | 0.00 | 0.00 | -0.01 |
| transSpecFlat | 0.12 | 0.00 | 0.11 | 0.02 | 0.00 | -0.01 | -0.01 | 0.00 | -0.01 | 0.12 | -0.10 | 0.24 | -0.14 | 0.02 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
| totCrest | -90.78 | -1.26 | -82.96 | -6.57 | -0.26 | -0.25 | 2.08 | -1.13 | -0.64 | 9.18 | 314.17 | -53.07 | 171.49 | -8.94 | 0.04 | -0.05 | 0.06 | -0.05 | -0.02 | 0.01 | -0.02 | 0.00 | 2.99 | 0.50 | -0.04 | 0.88 |
| attCrest | -13.10 | -0.26 | -12.27 | -0.57 | -0.05 | 0.01 | 0.38 | -0.10 | -0.06 | -3.27 | 49.56 | -16.77 | 29.11 | -1.05 | 0.01 | -0.01 | 0.01 | -0.01 | 0.00 | 0.00 | 0.00 | 0.00 | 0.50 | 0.11 | -0.01 | 0.14 |
| decCrest | 27.04 | -0.03 | 25.25 | 1.83 | -0.01 | -0.77 | -0.61 | -0.53 | -0.63 | 1.29 | -7.49 | -0.43 | 4.67 | 1.79 | -0.01 | 0.00 | -0.01 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | -0.04 | -0.01 | 0.29 | -0.04 |
| transCrest | -39.39 | -0.40 | -35.30 | -3.68 | -0.08 | 0.40 | 1.09 | 0.06 | 0.24 | 5.57 | 83.34 | -13.80 | 61.51 | -4.55 | 0.01 | -0.01 | 0.02 | -0.02 | -0.01 | 0.00 | -0.01 | 0.00 | 0.88 | 0.14 | -0.04 | 0.34 |
heatmap(cov_mat)
Sofia, on 2020-07-07: “The main hypothesis is that playing instruction (N/C) will affect the stroke in a way that is perceivable”.
transSCLooking at the variables agreed upon I have decided to use as response variables in the regression models—implying that this is by no means set in stone—, it seems like a skewed normal link function would be appropriate to model them.
Let’s start with transSC. Using an extended model description language (Bates 2010; Bürkner 2018), going back to Wilkinson and Rogers’s (1973) modeling language, we write:totDur
(m0_form <-bf(transSC ~ 1 + (1 | subj)))
transSC ~ 1 + (1 | subj)
which claims that transSC is explained by (‘~’) an intercept, denoted by ‘1’, and an additional term ‘(1 | subj)’. The ‘1’ in parentheses again stands for the intercept, but the pipe ‘|’ assigns an intercept to each level of the factor ‘subj’. In this particular case this means that the model will estimate an individual intercept for each unique drummer listed in the data set column subj. These individual, or varying, intercepts are then used in informing the estimation of the population intercept.
Note: set MODEL to TRUE at the top of the script if you haven’t compile/build your model yet.
if (MODEL) {
m0 <- brm(m0_form,
family = skew_normal(),
inits = "0",
data = drum_beats)
m0 <- add_criterion(m0,
"loo",
reloo = TRUE)
save(m0,
file = "m0.rda")
} else {
load("m0.rda")
}
This null model is also termed unconditional model because it has no grouping structure apart from individuals–the ‘subj’ bit in the model equation above. There is some variation in every natural data set. To make sure, it’s not just variation caused by different participants, we can calculate the intra-class correlation coefficient (ICC).
m0_icc <- ICC(m0, "subj")
The Null model’s ICC amounts to 0.75, which suggests that approx. 75 percent of the variation in the data set can be attributed to (or explained by) the grouping structure. This is highly unfortunate, as it does not leave a lot of variation to be explained by independent factors like instruction, or arm. The most likely reason for this high ICC value is the small sample size combined with high inter-individual variation. Small sample sizes combined with large trial numbers are less of a problem when subjects respond, on average, close to the population mean, even with large spread due to fluctuating alertness, increasing fatigue etc., .e.g. in reaction time paradigms. But here, with large intra- and inter-individual variation, this might become a problem.
Tab. 1. Model summary.
(m0_summary <- summary(m0,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = identity; alpha = identity
Formula: transSC ~ 1 + (1 | subj)
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
alpha ~ normal(0, 4)
Intercept ~ student_t(3, 735, 136.5)
sd ~ student_t(3, 0, 136.5)
sigma ~ student_t(3, 0, 136.5)
Group-Level Effects:
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 113.85 32.64 67.86 191.10 1.01 649 1076
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
Intercept 750.12 37.86 679.46 829.76 1.01 754 1114
Family Specific Parameters:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sigma 64.96 1.51 62.18 68.05 1.00 1862 1835
alpha 3.14 0.33 2.51 3.83 1.00 2013 1737
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
The intercept in Tab. 1 amounts to roughly 750. In this model specification, the intercept is identical to the data set average. The table also shows that the inter-individual standard deviation (sd(Intercept)) is large compared to the unexplained variation (sigma). This led to the large ICC value above. By adding more and more independent factors to the model specification, we will later try to decrease \(\sigma\), i.e. ‘explain away’ as much remaining variation as possible.
pp_check(m0, nsamples = 100)
Fig. 6. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
The posterior predictive plot in Fig. 6 gives an impression on how the null model would generate data, given the parameters it estimated from the empirical data. As the thick line deviates from the modeled thin lines, especially on the left and the right side of the peak of the distribution, it is apparent that the model can be improved.
# conditional_effects(m0)
In this model, the intercept is complemented with second ‘main’ or population effect, the grouping variable patient:
(m1_form <- bf(transSC ~ 1 + patient +
(1 | subj)))
transSC ~ 1 + patient + (1 | subj)
I could have also specified the model without the explicit ‘1 +’, as the intercept is implicitly included in the model unless I explicitly exclude it. From now on I will always save some extra typing by refraining from explicitly indluding the intercept in models.
So now the model not only contains the individuals as grouping structure to ‘explain away’ variation, but also whether they belong to the patients or the healthy subjects.
The prior distributions in Bayesian models reflect the knowledge about the estimated parameters. The package brms automatically places weakly informative priors on parameters as soft contraints. But with more complex models involving varying parameter estimates, the statistical back end which does the heavy lifting, needs stronger priors particularly on these parameters, otherwise models don’t converge. The parameters most vulnerable to outliers in the data are the varying effects parameters, or random effects in traditional statistics. Therefore we place a stronger prior probability distribution over the estimate of the SD of individual intercepts:
(m1_prior <- set_prior("normal(0, 10)", class = "sd"))
sd ~ normal(0, 10)
and leave the rest of the priors as suggested by the package brms (see Tab. 2 for their priors).
if (MODEL) {
m1 <- brm(m1_form,
prior = m1_prior,
inits = "0",
family = skew_normal(),
data = drum_beats)
m1 <- add_criterion(m1,
"loo",
reloo = TRUE)
save(m1,
file = "m1.rda")
} else {
load("m1.rda")
}
Tab. 2. Model summary.
(m1_summary <- summary(m1,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = identity; alpha = identity
Formula: transSC ~ 1 + patient + (1 | subj)
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
alpha ~ normal(0, 4)
Intercept ~ student_t(3, 735, 136.5)
sd ~ normal(0, 10)
sigma ~ student_t(3, 0, 136.5)
Group-Level Effects:
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 49.15 4.79 40.35 58.93 1.00 1884 2233
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
Intercept 762.94 24.83 713.98 810.08 1.00 1417 1751
patient1 -26.51 34.40 -93.82 41.08 1.00 1611 1875
Family Specific Parameters:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sigma 65.12 1.57 62.09 68.18 1.00 2734 2436
alpha 3.26 0.35 2.63 3.98 1.00 3064 2748
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
The intercept in Tab. 2 amounts to roughly 763. In this model specification, the intercept is identical to the controlled strokes, while the patient1 value is the mean of the posterior distribution difference between the healthy subjects and the patients (-27). The table also shows that the interindividual standard deviation (sd(Intercept) \(\approx\) 49 is still large compared to the unexplained variation (sigma \(\approx\) 65).
pp_check(m1, nsamples = 100)
Fig. 7. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
The posterior predictive plot in Fig. 7 gives an impression on how this model would generate data, given the parameters it estimated from the empirical data. There is not much change from Fig. 6, which is not very surprising given the small estimated difference between the groups.
conditional_effects(m1,
dpar = "mu")
In this model, the intercept is complemented with second ‘main’ or population effect, the instruction condition cond:
(m2_form <-bf(transSC ~ patient + cond +
(1 | subj)))
transSC ~ patient + cond + (1 | subj)
So now the model also contains the individuals as grouping structure to ‘explain away’ variation, but also the manipulations.
The prior distributions in Bayesian models reflect the knowledge about the estimated parameters. The package brms automatically places weakly informative priors on parameters as soft contraints. But with more complex models involving varying parameter estimates, the statistical back end which does the heavy lifting, needs stronger priors particularly on these parameters, otherwise models don’t converge. The parameters most vulnerable to outliers in the data are the varying effects parameters, or random effects in traditional statistics. Therefore we place a stronger prior probability distribution over the estimate of the SD of individual intercepts:
(m2_prior <- c(set_prior("normal(0, 3)", class = "sd"),
set_prior("normal(0, 3)", class = "sigma"),
set_prior("normal(0, 2)", class = "alpha")))
prior class coef group resp dpar nlpar bound source
normal(0, 3) sd user
normal(0, 3) sigma user
normal(0, 2) alpha user
and leave the rest of the priors as suggested by the package brms (see Tab. 3 for their priors).
if (MODEL) {
m2 <- brm(m2_form,
prior = m2_prior,
family = skew_normal(),
inits = "0",
data = drum_beats)
m2 <- add_criterion(m2,
"loo",
reloo = TRUE)
save(m2,
file = "m2.rda")
} else {
load("m2.rda")
}
Tab. 3. Model summary.
(m2_summary <- summary(m2,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = identity; alpha = identity
Formula: transSC ~ patient + cond + (1 | subj)
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
alpha ~ normal(0, 2)
Intercept ~ student_t(3, 735, 136.5)
sd ~ normal(0, 3)
sigma ~ normal(0, 3)
Group-Level Effects:
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 29.32 1.53 26.42 32.31 1.00 2957 2716
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
Intercept 779.75 14.93 750.33 808.62 1.00 1456 1834
patient1 -27.61 20.71 -67.51 13.79 1.00 1420 2031
condN -41.21 3.40 -48.01 -34.42 1.00 4440 2939
Family Specific Parameters:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sigma 52.38 0.93 50.61 54.28 1.00 4468 2827
alpha 1.80 0.23 1.36 2.27 1.00 4016 2679
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
The intercept in Tab. 3 amounts to roughly 780. In this model specification, the intercept is identical to the controlled strokes, while the condN value is the mean of the posterior distribution difference between controlled and normal strokes (-41). The table also shows that the interindividual standard deviation (sd(Intercept) \(\approx\) 29 is still large compared to the unexplained variation (sigma \(\approx\) 52).
pp_check(m2, nsamples = 100)
Fig. 8. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
The posterior predictive plot in Fig. 8 gives an impression on how this model would generate data, given the parameters it estimated from the empirical data. There is not much change from Fig. 6, which is not very surprising given the small estimated difference between the conditions.
beautify_my_plot(plot(conditional_effects(m2,
dpar = "mu"),
plot = FALSE))
The last model included the instruction condition, more realistically reflecting the true structure of the data set. But it did not acknowledge that each subject executed several strokes in each of these conditions. This model includes a term with a varying intercept (VI) for condition to reflect just that, which will also assist in more realistically estimate the population effect of cond:
(m3_form <- bf(transSC ~ patient + cond +
(1 | subj) +
(1 | cond)))
transSC ~ patient + cond + (1 | subj) + (1 | cond)
Including more varying parameters in the model requires the prior on them to be even stronger:
(m3_prior <- m2_prior)
prior class coef group resp dpar nlpar bound source
normal(0, 3) sd user
normal(0, 3) sigma user
normal(0, 2) alpha user
if (MODEL) {
m3 <- brm(m3_form,
prior = m3_prior,
family = skew_normal(),
inits = "0",
data = drum_beats)
m3 <- add_criterion(m3,
"loo",
reloo = TRUE)
save(m3,
file = "m3.rda")
} else {
load("m3.rda")
}
Tab. 4. Model summary.
(m3_summary <- summary(m3,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = identity; alpha = identity
Formula: transSC ~ patient + cond + (1 | subj) + (1 | cond)
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
alpha ~ normal(0, 2)
Intercept ~ student_t(3, 735, 136.5)
sd ~ normal(0, 3)
sigma ~ normal(0, 3)
Group-Level Effects:
~cond (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.40 1.81 0.11 6.78 1.00 2782 2302
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 29.29 1.52 26.49 32.40 1.00 2958 2312
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
Intercept 780.37 14.81 751.07 810.05 1.00 1760 1980
patient1 -27.47 20.03 -66.99 11.40 1.00 1867 2420
condN -41.22 5.45 -52.17 -29.71 1.00 2758 2272
Family Specific Parameters:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sigma 52.38 0.93 50.58 54.18 1.00 4750 3046
alpha 1.80 0.23 1.35 2.26 1.00 4524 3358
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
The intercept in Tab. 4 amounts to roughly 780. In this model specification, the intercept is identical to the controlled strokes, while the condN value is the mean of the posterior distribution difference between controlled and normal strokes (-41). The table also shows that the inter-individual standard deviation (sd(Intercept) \(\approx\) 29 is not large anymore compared to the unexplained variation (sigma \(\approx\) 52).
pp_check(m3, nsamples = 100)
Fig. 9. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
The posterior predictive plot in Fig. 9 gives an impression on how this model would generate data, given the parameters it estimated from the empirical data. There is not much change from Fig. 6, which is not very surprising given the small estimated difference between the conditions.
beautify_my_plot(plot(conditional_effects(m3,
dpar = "mu"),
plot = FALSE))
The last model included the instruction condition, more realistically reflecting the true structure of the data set. But it did not acknowledge that each subject executed several strokes in each of these conditions. This model includes a term with a varying intercept (VI) for condition to reflect just that, which will also assist in more realistically estimate the population effect of cond:
(m4_form <- bf(transSC ~ patient * cond +
(1 | subj) +
(1 | cond)))
transSC ~ patient * cond + (1 | subj) + (1 | cond)
Including more varying parameters in the model requires the prior on them to be even stronger:
(m4_prior <- m3_prior)
prior class coef group resp dpar nlpar bound source
normal(0, 3) sd user
normal(0, 3) sigma user
normal(0, 2) alpha user
if (MODEL) {
m4 <- brm(m4_form,
prior = m4_prior,
family = skew_normal(),
inits = "0",
data = drum_beats)
m4 <- add_criterion(m4,
"loo",
reloo = TRUE)
save(m4,
file = "m4.rda")
} else {
load("m4.rda")
}
Tab. 5. Model summary.
(m4_summary <- summary(m4,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = identity; alpha = identity
Formula: transSC ~ patient * cond + (1 | subj) + (1 | cond)
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
alpha ~ normal(0, 2)
Intercept ~ student_t(3, 735, 136.5)
sd ~ normal(0, 3)
sigma ~ normal(0, 3)
Group-Level Effects:
~cond (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.42 1.85 0.08 6.94 1.00 2417 1562
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 29.28 1.50 26.48 32.32 1.00 3031 2855
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
Intercept 780.54 15.59 749.90 811.04 1.00 1591 1940
patient1 -28.57 21.59 -70.62 14.01 1.00 1777 2195
condN -42.48 6.09 -54.51 -30.22 1.00 2734 2404
patient1:condN 2.43 6.30 -10.08 14.50 1.00 3836 3084
Family Specific Parameters:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sigma 52.38 0.93 50.58 54.23 1.00 4832 2661
alpha 1.81 0.23 1.38 2.27 1.00 4316 2874
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
The intercept in Tab. 5 amounts to roughly 781. In this model specification, the intercept is identical to the controlled strokes, while the condN value is the mean of the posterior distribution difference between controlled and normal strokes (-42). The table also shows that the inter-individual standard deviation (sd(Intercept) \(\approx\) 29 is not large anymore compared to the unexplained variation (sigma \(\approx\) 52).
pp_check(m4, nsamples = 100)
Fig. 10. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
The posterior predictive plot in Fig. 10 gives an impression on how this model would generate data, given the parameters it estimated from the empirical data. There is not much change from Fig. 6, which is not very surprising given the small estimated difference between the conditions.
beautify_my_plot(plot(conditional_effects(m4,
dpar = "mu"),
plot = FALSE))
(m5_form <- bf(transSC ~ patient * cond + arm +
(1 | subj) +
(1 | cond)))
transSC ~ patient * cond + arm + (1 | subj) + (1 | cond)
(m5_prior <- m4_prior)
prior class coef group resp dpar nlpar bound source
normal(0, 3) sd user
normal(0, 3) sigma user
normal(0, 2) alpha user
if (MODEL) {
m5 <- brm(m5_form,
prior = m5_prior,
family = skew_normal(),
inits = "0",
data = drum_beats)
m5 <- add_criterion(m5,
"loo",
reloo = TRUE)
save(m5,
file = "m5.rda")
} else {
load("m5.rda")
}
Tab. 6. Model summary.
(m5_summary <- summary(m5,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = identity; alpha = identity
Formula: transSC ~ patient * cond + arm + (1 | subj) + (1 | cond)
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
alpha ~ normal(0, 2)
Intercept ~ student_t(3, 735, 136.5)
sd ~ normal(0, 3)
sigma ~ normal(0, 3)
Group-Level Effects:
~cond (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.42 1.78 0.11 6.65 1.00 2735 1793
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 29.31 1.55 26.39 32.46 1.00 3100 2530
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
Intercept 780.33 14.76 750.33 808.40 1.00 1314 2017
patient1 -28.56 20.76 -68.90 11.88 1.00 1732 2200
condN -42.44 6.37 -55.14 -30.14 1.00 2926 2260
armND 1.93 3.01 -4.01 7.76 1.00 5235 3127
patient1:condN 2.45 6.33 -9.85 15.02 1.00 3965 2984
Family Specific Parameters:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sigma 52.41 0.93 50.62 54.27 1.00 5048 3105
alpha 1.81 0.23 1.38 2.27 1.00 4498 2708
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
In the Population-Level Effects section of Tab. 6 are now two estimates for the skewness parameter alpha (one for the controlled [alpha_Intercept] and one for the normal condition [alpha_condN]), while there is no entry for alpha in the Family Specific section anymore. All this due to our explicit modeling of alpha conditional on instruction condition.
pp_check(m5, nsamples = 100)
Fig. 11. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
beautify_my_plot(plot(conditional_effects(m5,
dpar = "mu"),
plot = FALSE))
(m6_form <-bf(transSC ~ patient * cond + arm +
(1 | subj) +
(1 | cond) +
(1 | arm)))
transSC ~ patient * cond + arm + (1 | subj) + (1 | cond) + (1 | arm)
(m6_prior <- m5_prior)
prior class coef group resp dpar nlpar bound source
normal(0, 3) sd user
normal(0, 3) sigma user
normal(0, 2) alpha user
if (MODEL) {
m6 <- brm(m6_form,
prior = m6_prior,
family = skew_normal(),
inits = "0",
data = drum_beats)
m6 <- add_criterion(m6,
"loo",
reloo = TRUE)
save(m6,
file = "m6.rda")
} else {
load("m6.rda")
}
Tab. 7. Model summary.
(m6_summary <- summary(m6,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = identity; alpha = identity
Formula: transSC ~ patient * cond + arm + (1 | subj) + (1 | cond) + (1 | arm)
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
alpha ~ normal(0, 2)
Intercept ~ student_t(3, 735, 136.5)
sd ~ normal(0, 3)
sigma ~ normal(0, 3)
Group-Level Effects:
~arm (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.39 1.79 0.10 6.65 1.00 2325 1465
~cond (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.42 1.77 0.13 6.66 1.00 2782 1894
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 29.28 1.50 26.45 32.25 1.00 3198 2601
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
Intercept 779.39 15.27 750.06 809.27 1.00 1647 2176
patient1 -28.08 21.18 -70.55 14.96 1.01 1610 1999
condN -42.47 6.26 -54.92 -29.72 1.00 2727 2477
armND 1.94 5.07 -8.39 12.18 1.00 2638 1969
patient1:condN 2.31 6.44 -10.59 15.07 1.00 4097 2793
Family Specific Parameters:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sigma 52.36 0.92 50.58 54.23 1.00 5449 3059
alpha 1.81 0.23 1.37 2.27 1.00 4531 2851
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
In the Population-Level Effects section of Tab. 7 are now two estimates for the skewness parameter alpha (one for the controlled [alpha_Intercept] and one for the normal condition [alpha_condN]), while there is no entry for alpha in the Family Specific section anymore. All this due to our explicit modeling of alpha conditional on instruction condition.
pp_check(m6, nsamples = 100)
Fig. 12. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
beautify_my_plot(plot(conditional_effects(m6,
dpar = "mu"),
plot = FALSE))
(m6a_form <-bf(transSC ~ patient * cond * arm +
(1 | subj) +
(1 | cond) +
(1 | arm)))
transSC ~ patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
(m6a_prior <- m6_prior)
prior class coef group resp dpar nlpar bound source
normal(0, 3) sd user
normal(0, 3) sigma user
normal(0, 2) alpha user
if (MODEL) {
m6a <- brm(m6a_form,
prior = m6a_prior,
family = skew_normal(),
inits = "0",
data = drum_beats)
m6a <- add_criterion(m6a,
"loo",
reloo = TRUE)
save(m6a,
file = "m6a.rda")
} else {
load("m6a.rda")
}
Tab. 8. Model summary.
(m6a_summary <- summary(m6a,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = identity; alpha = identity
Formula: transSC ~ patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
alpha ~ normal(0, 2)
Intercept ~ student_t(3, 735, 136.5)
sd ~ normal(0, 3)
sigma ~ normal(0, 3)
Group-Level Effects:
~arm (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.41 1.80 0.10 6.71 1.00 2833 1943
~cond (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.37 1.79 0.10 6.40 1.00 3087 2103
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 29.38 1.52 26.52 32.46 1.00 3311 2956
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
Intercept 784.68 16.25 752.70 816.08 1.00 1414
patient1 -42.46 22.19 -87.54 -0.31 1.00 1516
condN -42.49 7.32 -56.89 -27.74 1.00 2531
armND -7.44 7.37 -22.23 6.82 1.00 2331
patient1:condN 8.85 8.86 -8.69 25.74 1.00 2429
patient1:armND 26.50 8.62 10.22 43.61 1.00 2276
condN:armND -0.28 8.44 -17.26 16.42 1.00 2172
patient1:condN:armND -13.59 12.42 -38.69 10.42 1.00 1939
Tail_ESS
Intercept 1835
patient1 1695
condN 2984
armND 2147
patient1:condN 3024
patient1:armND 2639
condN:armND 2740
patient1:condN:armND 2398
Family Specific Parameters:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sigma 52.16 0.93 50.40 53.98 1.00 5417 2475
alpha 1.68 0.23 1.22 2.15 1.00 5103 2958
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
In the Population-Level Effects section of Tab. 8 are now two estimates for the skewness parameter alpha (one for the controlled [alpha_Intercept] and one for the normal condition [alpha_condN]), while there is no entry for alpha in the Family Specific section anymore. All this due to our explicit modeling of alpha conditional on instruction condition.
pp_check(m6a, nsamples = 100)
Fig. 13. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
beautify_my_plot(plot(conditional_effects(m6a,
dpar = "mu"),
plot = FALSE))
conditions <- make_conditions(drum_beats,
vars = "arm")
beautify_my_plot(plot(conditional_effects(m6a,
dpar = "mu",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
As is apparent from Fig. 1, the controlled condition yielded broader density distributions in most descriptors. Hence, we model condition-dependent variation in the next model:
(m7_form <-bf(transSC ~ patient * cond * arm +
(1 | subj) +
(1 | cond) +
(1 | arm),
sigma ~ cond))
transSC ~ patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ cond
This model has now two outcomes, not just one, as the models before. Spread is estimated as sigma, and it varies conditional on instruction condition.
Here’s the non-standard (additional) prior:
(m7_prior <- c(set_prior("normal(0, 5)", class = "sd"),
set_prior("normal(0, 2)", class = "alpha"),
set_prior("normal(0, 10)", class = "Intercept", dpar = "sigma"),
set_prior("normal(0, 10)", class = "b", dpar = "sigma")
))
prior class coef group resp dpar nlpar bound source
normal(0, 5) sd user
normal(0, 2) alpha user
normal(0, 10) Intercept sigma user
normal(0, 10) b sigma user
if (MODEL) {
m7 <- brm(m7_form,
prior = m7_prior,
family = skew_normal(),
inits = "0",
data = drum_beats)
m7 <- add_criterion(m7,
"loo",
reloo = TRUE)
save(m7,
file = "m7.rda")
} else {
load("m7.rda")
}
Tab. 9. Model summary.
(m7_summary <- summary(m7,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = log; alpha = identity
Formula: transSC ~ patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ cond
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
alpha ~ normal(0, 2)
b_sigma ~ normal(0, 10)
Intercept ~ student_t(3, 735, 136.5)
Intercept_sigma ~ normal(0, 10)
sd ~ normal(0, 5)
Group-Level Effects:
~arm (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 3.98 3.03 0.13 11.25 1.00 2790 1666
~cond (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 3.97 3.01 0.15 11.20 1.00 3106 1745
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 35.46 2.50 30.83 40.50 1.00 3949 2693
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
Intercept 788.13 19.80 749.83 827.07 1.00 1788
sigma_Intercept 4.30 0.04 4.23 4.37 1.00 5782
patient1 -40.69 25.90 -89.84 9.06 1.00 1842
condN -45.48 9.71 -65.24 -25.49 1.00 2957
armND -9.17 10.85 -30.43 12.46 1.00 2667
patient1:condN 7.44 10.29 -12.24 27.85 1.00 3088
patient1:armND 24.81 11.72 2.38 48.06 1.00 2806
condN:armND 0.15 9.78 -19.17 19.47 1.00 3004
patient1:condN:armND -10.34 14.06 -37.23 17.25 1.00 2714
sigma_condN -0.46 0.06 -0.57 -0.35 1.00 5958
Tail_ESS
Intercept 2580
sigma_Intercept 3021
patient1 2305
condN 2539
armND 2530
patient1:condN 3054
patient1:armND 2842
condN:armND 3159
patient1:condN:armND 2998
sigma_condN 2814
Family Specific Parameters:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
alpha 2.25 0.29 1.69 2.84 1.00 4889 3156
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
In the Links section of the summary (Tab. 9) we note that sigma is no longer modeled on the identity scale but on the \(\log_{2}\) scale. In the Population-Level Effects section of Tab. 9 we now find not only the estimates for the Intercept and condN but also two estimates for sigma (one for the controlled [sigma_Intercept] and one for the normal condition [sigma_condN]). Because of this, there is no entry for sigma in the Family Specific section anymore. All this due to our explicit modeling of sigma conditional on instruction condition.
pp_check(m7, nsamples = 100)
Fig. 14. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
beautify_my_plot(plot(conditional_effects(m7,
dpar = "mu"),
plot = FALSE))
conditions <- make_conditions(drum_beats,
vars = "arm")
beautify_my_plot(plot(conditional_effects(m7,
dpar = "mu",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m7,
dpar = "sigma"),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m7,
dpar = "sigma",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
Fig. 15. Conditional plot.
In Fig. 15 we see a difference between the mean (‘mu’) estimated value for transSC depending on instruction condition (A), but no difference between dominant and non-dominant arm (B). Consequently, there is no interaction in (C).
The spread (sigma) of the estimated distributions also differs between conditions (D), but again not between arms (E). The latter is not surprising because we modeled sigma to vary conditional on condition, not arm.
At least in some descriptors in Fig. 1 the skewness of the distribution seems to change depending on the arm. The skew normal distribution is a generalization of the Gaussian distribution, allowing for the additional shape-parameter skewness (asymmetry) to vary. Hence, we model this side-dependent skewness in the next model:
(m8_form <-bf(transSC ~ patient * cond * arm +
(1 | subj) +
(1 | cond) +
(1 | arm),
sigma ~ cond,
alpha ~ arm))
transSC ~ patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ cond
alpha ~ arm
(m8_prior <- c(set_prior("normal(0, 3)", class = "sd"),
set_prior("normal(0, 10)", class = "Intercept", dpar = "sigma"),
set_prior("normal(0, 10)", class = "b", dpar = "sigma"),
set_prior("normal(0, 2)", class = "Intercept", dpar = "alpha"),
set_prior("normal(0, 2)", class = "b", dpar = "alpha"))
)
prior class coef group resp dpar nlpar bound source
normal(0, 3) sd user
normal(0, 10) Intercept sigma user
normal(0, 10) b sigma user
normal(0, 2) Intercept alpha user
normal(0, 2) b alpha user
if (MODEL) {
m8 <- brm(m8_form,
prior = m8_prior,
family = skew_normal(),
inits = "0",
data = drum_beats)
m8 <- add_criterion(m8,
"loo",
reloo = TRUE)
save(m8,
file = "m8.rda")
} else {
load("m8.rda")
}
Tab. 10. Model summary.
(m8_summary <- summary(m8,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = log; alpha = identity
Formula: transSC ~ patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ cond
alpha ~ arm
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
b_alpha ~ normal(0, 2)
b_sigma ~ normal(0, 10)
Intercept ~ student_t(3, 735, 136.5)
Intercept_alpha ~ normal(0, 2)
Intercept_sigma ~ normal(0, 10)
sd ~ normal(0, 3)
Group-Level Effects:
~arm (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.44 1.85 0.09 6.97 1.00 3149 1990
~cond (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.33 1.82 0.10 6.73 1.00 2464 1735
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 27.38 1.52 24.55 30.37 1.00 2861 2595
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
Intercept 789.03 15.46 758.86 818.31 1.00 1522
sigma_Intercept 4.34 0.04 4.27 4.41 1.00 4350
alpha_Intercept 1.69 0.40 0.88 2.44 1.00 4068
patient1 -45.01 21.81 -87.98 -1.88 1.00 1549
condN -44.90 8.22 -61.63 -29.12 1.00 1920
armND -9.92 9.50 -28.20 9.15 1.00 2128
patient1:condN 9.90 10.80 -10.97 31.86 1.00 2020
patient1:armND 28.03 11.99 3.89 51.23 1.00 2101
condN:armND -1.00 9.74 -19.38 18.03 1.00 2113
patient1:condN:armND -10.77 13.94 -39.14 16.94 1.00 1946
sigma_condN -0.52 0.06 -0.62 -0.41 1.00 4594
alpha_armND 1.68 0.54 0.66 2.78 1.00 3981
Tail_ESS
Intercept 2200
sigma_Intercept 3193
alpha_Intercept 1932
patient1 2074
condN 2522
armND 2486
patient1:condN 2631
patient1:armND 2394
condN:armND 2647
patient1:condN:armND 2179
sigma_condN 3519
alpha_armND 2286
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
In the Population-Level Effects section of Tab. 10 are now two estimates for the skewness parameter alpha (one for the dominant [alpha_Intercept] and one for the non-dominant arm [alpha_armND]), while there is no entry for alpha in the Family Specific section anymore. All this due to our explicit modeling of alpha conditional on arm.
pp_check(m8, nsamples = 100)
Fig. 16. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
beautify_my_plot(plot(conditional_effects(m8,
dpar = "mu"),
plot = FALSE))
conditions <- make_conditions(drum_beats,
vars = "arm")
beautify_my_plot(plot(conditional_effects(m8,
dpar = "mu",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m8,
dpar = "sigma"),
plot = FALSE))
conditional_effects(m8,
dpar = "sigma",
effects = "patient:cond",
conditions = conditions)
beautify_my_plot(plot(conditional_effects(m8,
dpar = "alpha"),
plot = FALSE))
conditional_effects(m8,
dpar = "alpha",
effects = "patient:cond",
conditions = conditions)
Fig. 17. Conditional plots.
In Fig. 17 there is a clear difference in estimated mean (‘mu’) of \(transSC\) conditional on instruction (A), but not on arm (B). Consequently, there is no interaction between instruction and arm (C). On the other hand, there is a difference in estimated skewness (‘alpha’) between sides (E), but not instructions (D). (F) follows from that. ‘sigma’ shows a clear difference between instructions (G), not so for side (H), which is mirrored in (I).
To be able to see whether skewness and spread are depending on both experimental manipulation and arm, the model formulas for ‘sigma’ and ‘alpha’ are updated accordingly:
(m9_form <-bf(transSC ~ patient * cond * arm +
(1 | subj) +
(1 | cond) +
(1 | arm),
sigma ~ cond,
alpha ~ arm))
transSC ~ patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ cond
alpha ~ arm
(m9_prior <- m8_prior)
prior class coef group resp dpar nlpar bound source
normal(0, 3) sd user
normal(0, 10) Intercept sigma user
normal(0, 10) b sigma user
normal(0, 2) Intercept alpha user
normal(0, 2) b alpha user
if (MODEL) {
m9 <- brm(m9_form,
prior = m9_prior,
family = skew_normal(),
inits = "0",
data = drum_beats)
m9 <- add_criterion(m9,
"loo",
reloo = TRUE)
save(m9,
file = "m9.rda")
} else {
load("m9.rda")
}
Tab. 11. Model summary.
(m9_summary <- summary(m9,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = log; alpha = identity
Formula: transSC ~ patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ cond
alpha ~ arm
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
b_alpha ~ normal(0, 2)
b_sigma ~ normal(0, 10)
Intercept ~ student_t(3, 735, 136.5)
Intercept_alpha ~ normal(0, 2)
Intercept_sigma ~ normal(0, 10)
sd ~ normal(0, 3)
Group-Level Effects:
~arm (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.38 1.77 0.11 6.71 1.00 2676 1975
~cond (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.40 1.83 0.09 6.76 1.00 3125 1902
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 27.35 1.48 24.66 30.40 1.00 3135 2794
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
Intercept 788.62 15.42 757.55 819.32 1.00 1650
sigma_Intercept 4.33 0.04 4.27 4.41 1.00 4564
alpha_Intercept 1.70 0.39 0.91 2.41 1.00 4718
patient1 -44.60 20.97 -84.80 -3.30 1.00 1520
condN -44.66 8.49 -61.44 -28.35 1.00 2385
armND -9.78 9.31 -28.83 9.30 1.00 2253
patient1:condN 9.76 10.66 -11.46 30.16 1.00 2365
patient1:armND 27.78 11.86 4.76 51.46 1.00 2084
condN:armND -1.33 9.81 -20.41 17.80 1.00 2255
patient1:condN:armND -10.42 13.94 -37.53 17.07 1.00 1991
sigma_condN -0.52 0.06 -0.63 -0.41 1.00 4776
alpha_armND 1.68 0.54 0.68 2.81 1.00 3549
Tail_ESS
Intercept 2021
sigma_Intercept 2859
alpha_Intercept 2179
patient1 2171
condN 2691
armND 2286
patient1:condN 2673
patient1:armND 2808
condN:armND 2388
patient1:condN:armND 2600
sigma_condN 3489
alpha_armND 2618
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
In the Population-Level Effects section of Tab. 11 are now three estimates for the skewness parameter alpha, as well as three estimates for spread (‘sigma’).
pp_check(m9, nsamples = 100)
Fig. 18. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
beautify_my_plot(plot(conditional_effects(m9,
dpar = "mu"),
plot = FALSE))
conditions <- make_conditions(drum_beats,
vars = "arm")
beautify_my_plot(plot(conditional_effects(m9,
dpar = "mu",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m9,
dpar = "sigma"),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m9,
dpar = "sigma",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m9,
dpar = "alpha"),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m9,
dpar = "alpha",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
Fig. 19. Conditional plots. Had to take out all the fancy figure polishing, subplot lettering etc. Subplots are supposed to be numbered from A to … starting in the top left corner, proceeding row-wise.
In Fig. 19 the dots are the means of the posterior distributions of the respective estimate, and can be interpreted similarly to the point estimates in traditional frequentist statistics. The error bars represent 95% credible intervals, which are interpreted as comprising the true value with 95% probability, given the model and the data.
There is a difference in estimated the mean (‘mu’) of \(transSC\) conditional on group (A) and condition (B), not so on arm (C). Likewise, there is a two-way interaction between group and arm (D), but not between condition and arm (E). Consequently, there is no three-way interaction (F).
The remaining, unexplained variation ‘sigma’ shows a clear difference between instructions (H) and lesser so for side (I), but albeit their opposing trends, there is no interaction (J thru M).
There is a difference in estimated skewness (‘alpha’) both between instruction (O) and side (P), but with opposing trends. Nevertheless, there is no interaction between them (Q thru T).
From a data-driven perspective this should lead to a simplification of the model, leaving out all the unnecessary interaction terms. A theory-driven approach though requires the final model to be ‘full’ in the sense that all explanatory variables must interact with all others, implying that not finding an interaction between factors either is due to there really not being an interaction–rendering the model mis-specified and proving the underlying theory wrong–, or due to insufficient data. Since the data set at hand is very small I vote to blame the failure to find interactions between all factors on the small sample size and would therefore keep all interactions in the model.
(m10_form <-bf(transSC ~ patient * cond * arm +
(1 | subj) +
(1 | cond) +
(1 | arm),
sigma ~ cond * arm,
alpha ~ cond * arm))
transSC ~ patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ cond * arm
alpha ~ cond * arm
(m10_prior <- m9_prior)
prior class coef group resp dpar nlpar bound source
normal(0, 3) sd user
normal(0, 10) Intercept sigma user
normal(0, 10) b sigma user
normal(0, 2) Intercept alpha user
normal(0, 2) b alpha user
if (MODEL) {
m10 <- brm(m10_form,
prior = m10_prior,
family = skew_normal(),
inits = "0",
data = drum_beats)
m10 <- add_criterion(m10,
"loo",
reloo = TRUE)
save(m10,
file = "m10.rda")
} else {
load("m10.rda")
}
Tab. 12. Model summary.
(m10_summary <- summary(m10,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = log; alpha = identity
Formula: transSC ~ patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ cond * arm
alpha ~ cond * arm
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
b_alpha ~ normal(0, 2)
b_sigma ~ normal(0, 10)
Intercept ~ student_t(3, 735, 136.5)
Intercept_alpha ~ normal(0, 2)
Intercept_sigma ~ normal(0, 10)
sd ~ normal(0, 3)
Group-Level Effects:
~arm (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.38 1.82 0.11 6.71 1.00 2890 1973
~cond (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.40 1.85 0.10 6.85 1.00 2889 1549
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 27.43 1.49 24.64 30.51 1.00 3338 2697
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
Intercept 787.49 15.76 757.26 818.15 1.00 1990
sigma_Intercept 4.29 0.05 4.20 4.39 1.00 3778
alpha_Intercept 4.36 0.65 3.21 5.69 1.00 4480
patient1 -37.74 21.07 -79.51 4.25 1.00 1934
condN -43.96 7.88 -59.48 -28.41 1.00 2878
armND -8.41 9.60 -27.39 10.10 1.00 2148
patient1:condN 2.03 9.19 -16.01 20.04 1.00 3044
patient1:armND 30.64 10.63 9.28 51.36 1.00 2631
condN:armND -3.62 9.96 -23.09 16.13 1.00 2283
patient1:condN:armND -13.69 12.69 -38.69 10.99 1.00 2458
sigma_condN -0.52 0.07 -0.66 -0.38 1.00 3518
sigma_armND 0.14 0.07 0.00 0.27 1.00 3584
sigma_condN:armND -0.18 0.09 -0.36 -0.01 1.00 3129
alpha_condN -5.34 0.85 -6.87 -3.48 1.00 2056
alpha_armND 2.07 0.99 0.23 4.13 1.00 3669
alpha_condN:armND 1.06 1.13 -1.24 3.17 1.00 2636
Tail_ESS
Intercept 2056
sigma_Intercept 3165
alpha_Intercept 3333
patient1 1933
condN 2860
armND 2461
patient1:condN 2765
patient1:armND 2747
condN:armND 2482
patient1:condN:armND 2283
sigma_condN 2943
sigma_armND 3220
sigma_condN:armND 2847
alpha_condN 2324
alpha_armND 2686
alpha_condN:armND 2857
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
pp_check(m10, nsamples = 100)
Fig. 20. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
beautify_my_plot(plot(conditional_effects(m10,
dpar = "mu"),
plot = FALSE))
conditions <- make_conditions(drum_beats,
vars = "arm")
beautify_my_plot(plot(conditional_effects(m10,
dpar = "mu",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m10,
dpar = "sigma"),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m10,
dpar = "sigma",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m10,
dpar = "alpha"),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m10,
dpar = "alpha",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
Fig. 21. Conditional plots. Had to take out all the fancy figure polishing, subplot lettering etc. Subplots are supposed to be numbered from A to … starting in the top left corner, proceeding row-wise.
In Fig. 21 the dots are the means of the posterior distributions of the respective estimate, and can be interpreted similarly to the point estimates in traditional frequentist statistics. The error bars represent 95% credible intervals, which are interpreted as comprising the true value with 95% probability, given the model and the data.
There is a difference in estimated the mean (‘mu’) of \(transSC\) conditional on group (A) and condition (B), not so on arm (C). Likewise, there is a two-way interaction between group and arm (D), but not between condition and arm (E). Consequently, there is no three-way interaction (F).
The remaining, unexplained variation ‘sigma’ shows a clear difference between instructions (H) and lesser so for side (I), but albeit their opposing trends, there is no interaction (J thru M).
There is a difference in estimated skewness (‘alpha’) both between instruction (O) and side (P), but with opposing trends. Nevertheless, there is no interaction between them (Q thru T).
From a data-driven perspective this should lead to a simplification of the model, leaving out all the unnecessary interaction terms. A theory-driven approach though requires the final model to be ‘full’ in the sense that all explanatory variables must interact with all others, implying that not finding an interaction between factors either is due to there really not being an interaction–rendering the model mis-specified and proving the underlying theory wrong–, or due to insufficient data. Since the data set at hand is very small I vote to blame the failure to find interactions between all factors on the small sample size and would therefore keep all interactions in the model.
(m11_form <-bf(transSC ~ patient * cond * arm +
(1 | subj) +
(1 | cond) +
(1 | arm),
sigma ~ patient * cond * arm,
alpha ~ patient * cond * arm))
transSC ~ patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ patient * cond * arm
alpha ~ patient * cond * arm
(m11_prior <- m10_prior)
prior class coef group resp dpar nlpar bound source
normal(0, 3) sd user
normal(0, 10) Intercept sigma user
normal(0, 10) b sigma user
normal(0, 2) Intercept alpha user
normal(0, 2) b alpha user
if (MODEL) {
m11 <- brm(m11_form,
prior = m11_prior,
family = skew_normal(),
inits = "0",
data = drum_beats)
m11 <- add_criterion(m11,
"loo",
reloo = TRUE)
save(m11,
file = "m11.rda")
} else {
load("m11.rda")
}
Tab. 13. Model summary.
(m11_summary <- summary(m11,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = log; alpha = identity
Formula: transSC ~ patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ patient * cond * arm
alpha ~ patient * cond * arm
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
b_alpha ~ normal(0, 2)
b_sigma ~ normal(0, 10)
Intercept ~ student_t(3, 735, 136.5)
Intercept_alpha ~ normal(0, 2)
Intercept_sigma ~ normal(0, 10)
sd ~ normal(0, 3)
Group-Level Effects:
~arm (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.43 1.80 0.09 6.68 1.00 3555 1988
~cond (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 2.38 1.80 0.09 6.58 1.00 3239 1820
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 27.35 1.52 24.48 30.46 1.00 5317 3089
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
Intercept 790.87 15.47 760.23 821.20 1.00 2069
sigma_Intercept 4.34 0.07 4.21 4.46 1.00 2757
alpha_Intercept 4.42 0.79 2.93 6.05 1.00 5108
patient1 -46.80 21.03 -87.09 -5.86 1.00 2022
condN -47.29 8.24 -63.89 -30.56 1.00 2758
armND -12.24 9.90 -31.78 7.64 1.00 2511
patient1:condN 10.71 10.24 -9.10 30.55 1.00 2798
patient1:armND 41.34 12.50 17.27 66.26 1.00 2295
condN:armND 1.58 10.44 -18.46 21.80 1.00 2501
patient1:condN:armND -26.69 14.81 -55.97 0.78 1.00 2339
sigma_patient1 -0.14 0.10 -0.34 0.05 1.00 2630
sigma_condN -0.54 0.11 -0.75 -0.33 1.00 2715
sigma_armND 0.05 0.10 -0.14 0.24 1.00 2961
sigma_patient1:condN 0.11 0.15 -0.19 0.40 1.00 2534
sigma_patient1:armND 0.21 0.14 -0.06 0.47 1.00 2400
sigma_condN:armND -0.03 0.13 -0.28 0.22 1.00 2606
sigma_patient1:condN:armND -0.33 0.18 -0.68 0.04 1.00 2345
alpha_patient1 -0.61 1.04 -2.61 1.48 1.00 5098
alpha_condN -5.11 1.09 -7.21 -3.07 1.00 2872
alpha_armND 0.65 1.19 -1.54 3.09 1.00 4233
alpha_patient1:condN 0.50 1.21 -1.80 2.81 1.00 3668
alpha_patient1:armND 2.94 1.31 0.40 5.50 1.00 4544
alpha_condN:armND 1.28 1.27 -1.27 3.68 1.00 3565
alpha_patient1:condN:armND -1.36 1.40 -4.16 1.37 1.00 4935
Tail_ESS
Intercept 2607
sigma_Intercept 3217
alpha_Intercept 3450
patient1 2258
condN 2997
armND 2434
patient1:condN 2749
patient1:armND 2674
condN:armND 2618
patient1:condN:armND 2507
sigma_patient1 2931
sigma_condN 2737
sigma_armND 3086
sigma_patient1:condN 2756
sigma_patient1:armND 2942
sigma_condN:armND 2908
sigma_patient1:condN:armND 3164
alpha_patient1 3227
alpha_condN 3761
alpha_armND 3205
alpha_patient1:condN 3085
alpha_patient1:armND 3517
alpha_condN:armND 3162
alpha_patient1:condN:armND 3264
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
pp_check(m11, nsamples = 100)
Fig. 22. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
beautify_my_plot(plot(conditional_effects(m11,
dpar = "mu"),
plot = FALSE))
conditions <- make_conditions(drum_beats,
vars = "arm")
beautify_my_plot(plot(conditional_effects(m11,
dpar = "mu",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m11,
dpar = "sigma"),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m11,
dpar = "sigma",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m11,
dpar = "alpha"),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m11,
dpar = "alpha",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
Fig. 23. Conditional plots. Had to take out all the fancy figure polishing, subplot lettering etc. Subplots are supposed to be numbered from A to … starting in the top left corner, proceeding row-wise.
In Fig. 23 the dots are the means of the posterior distributions of the respective estimate, and can be interpreted similarly to the point estimates in traditional frequentist statistics. The error bars represent 95% credible intervals, which are interpreted as comprising the true value with 95% probability, given the model and the data.
There is a difference in estimated the mean (‘mu’) of \(transSC\) conditional on group (A) and condition (B), not so on arm (C). Likewise, there is a two-way interaction between group and arm (D), but not between condition and arm (E). Consequently, there is no three-way interaction (F).
The remaining, unexplained variation ‘sigma’ shows a clear difference between instructions (H) and lesser so for side (I), but albeit their opposing trends, there is no interaction (J thru M).
There is a difference in estimated skewness (‘alpha’) both between instruction (O) and side (P), but with opposing trends. Nevertheless, there is no interaction between them (Q thru T).
From a data-driven perspective this should lead to a simplification of the model, leaving out all the unnecessary interaction terms. A theory-driven approach though requires the final model to be ‘full’ in the sense that all explanatory variables must interact with all others, implying that not finding an interaction between factors either is due to there really not being an interaction–rendering the model mis-specified and proving the underlying theory wrong–, or due to insufficient data. Since the data set at hand is very small I vote to blame the failure to find interactions between all factors on the small sample size and would therefore keep all interactions in the model.
We compare models by their estimated log-posterior density (elpd). The smaller this value the better a model predicts the data, despite the penalty for additional covariates. When the difference between two models is more than two SE apart they are considered to be ‘different enough’ to warrant acceptance of one over the other despite possibly smaller parsimony.
univ_model_compar <- loo_compare(m0, m2, m3, m5, m6, m6a, m7, m8, m9, m10, m11)
print(univ_model_compar, simplify = T)
elpd_diff se_diff
m10 0.0 0.0
m11 -1.4 3.6
m9 -40.1 8.9
m8 -40.5 8.9
m7 -43.5 9.9
m6a -82.5 15.8
m2 -83.1 16.7
m3 -83.3 16.7
m5 -85.1 16.8
m6 -85.4 16.8
m0 -121.9 15.5
The model with the smallest elpd is m10, which corresponds to the second to last model (see Modeling Interactions of Arm and Instruction on Shape and Spread). The difference between the best and the second-best model (m11, Modeling the Influence of Group on Shape and Spread) is -1.38, which is less than roughly two SE (2 x 3.57 = 7.15) away from 0.
The fact that the full model turned out to be the best-fitting one suggests that the data really are best fit by this model, and that the patient term and the interaction terms really should remain in the model.
wrap_plots(plot(conditional_effects(m10,
dpar = "mu",
effects = "patient:cond",
conditions = conditions),
plot = FALSE)[[1]] +
scale_color_colorblind() +
theme(legend.position = "none"),
plot(conditional_effects(m10,
dpar = "sigma",
effects = "patient:cond",
conditions = conditions),
plot = FALSE)[[1]] +
scale_color_colorblind() +
theme(legend.position = "none"),
plot(conditional_effects(m10,
dpar = "alpha",
effects = "patient:cond",
conditions = conditions),
plot = FALSE)[[1]]) +
scale_color_colorblind() +
plot_annotation(tag_levels = "A")
Fig. 24. Three-way interaction plots of the three modeled parameters \(\mu\), \(\sigma\), and \(\alpha\) as estimated by the best-fitting model. The x axis shows group membership (0 = healthy subjects, 1 = patients). The instruction conditions are color-coded (black = controlled strokes, brown = normal strokes), and the facets show the side (1 = dominant, 2 = non-dominant).
Fig. 24A suggests that \(\mu\) is higher for healthy subjects than for patients, and higher for controlled strokes than for normal strokes which is really odd on an intuitive level and seems contradictive (at least to me). I would’ve expected transSC to
Fig. 24N might clarify why this is the case, because it shows a higher unexplained variation in the data for controlled strokes as compared to normal strokes.
(see e.g., here,
On a different level of understanding these results mean that transSC is lower in the normal strokes, with almost no skewness (alpha is close to zero) and lower spread than in controlled strokes.
transFlat(m10_transFlat_form <-bf(transFlat ~ 0 + Intercept + patient * cond * arm +
(1 | subj) +
(1 | cond) +
(1 | arm),
sigma ~ cond * arm,
alpha ~ cond * arm))
transFlat ~ 0 + Intercept + patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ cond * arm
alpha ~ cond * arm
(m10_transFlat_prior <- c(set_prior("normal(0.8, 10)", class = "b", coef = "Intercept"),
set_prior("normal(0, 10)", class = "b"),
set_prior("normal(0, 5)", class = "b", coef = "armND"),
set_prior("normal(0, 5)", class = "b", coef = "condN"),
set_prior("normal(0, 0.01)", class = "sd"),
set_prior("normal(0, 5)", class = "Intercept", dpar = "sigma"),
set_prior("normal(0, 5)", class = "b", dpar = "sigma"),
set_prior("normal(0, 2)", class = "Intercept", dpar = "alpha"),
set_prior("normal(0, 2)", class = "b", dpar = "alpha")
))
prior class coef group resp dpar nlpar bound source
normal(0.8, 10) b Intercept user
normal(0, 10) b user
normal(0, 5) b armND user
normal(0, 5) b condN user
normal(0, 0.01) sd user
normal(0, 5) Intercept sigma user
normal(0, 5) b sigma user
normal(0, 2) Intercept alpha user
normal(0, 2) b alpha user
if (MODEL) {
m10_transFlat <- brm(m10_transFlat_form,
prior = m10_transFlat_prior,
family = skew_normal(),
inits = "0",
data = drum_beats)
m10_transFlat <- add_criterion(m10_transFlat,
"loo",
reloo = TRUE)
save(m10_transFlat,
file = "m10_transFlat.rda")
} else {
load("m10_transFlat.rda")
}
Tab. 14. Model summary. The model has not converged.
(m10_transFlat_summary <- summary(m10_transFlat,
priors = TRUE))
Warning: There were 28 divergent transitions after warmup. Increasing
adapt_delta above 0.8 may help. See http://mc-stan.org/misc/
warnings.html#divergent-transitions-after-warmup
Family: skew_normal
Links: mu = identity; sigma = log; alpha = identity
Formula: transFlat ~ 0 + Intercept + patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ cond * arm
alpha ~ cond * arm
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
b ~ normal(0, 10)
b_armND ~ normal(0, 5)
b_condN ~ normal(0, 5)
b_Intercept ~ normal(0.8, 10)
b_alpha ~ normal(0, 2)
b_sigma ~ normal(0, 5)
Intercept_alpha ~ normal(0, 2)
Intercept_sigma ~ normal(0, 5)
sd ~ normal(0, 0.01)
Group-Level Effects:
~arm (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 0.01 0.01 0.00 0.02 1.00 2670 1987
~cond (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 0.01 0.01 0.00 0.02 1.00 2617 2046
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 0.02 0.00 0.02 0.03 1.00 2501 2671
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
sigma_Intercept -3.62 0.05 -3.72 -3.52 1.00 3452
alpha_Intercept -4.18 0.63 -5.56 -3.08 1.00 3968
Intercept 0.71 0.02 0.67 0.75 1.00 1692
patient1 0.04 0.02 0.01 0.08 1.00 1785
condN 0.02 0.01 -0.01 0.05 1.00 1481
armND 0.01 0.01 -0.02 0.04 1.00 2175
patient1:condN -0.01 0.00 -0.02 -0.00 1.00 4560
patient1:armND -0.03 0.00 -0.04 -0.02 1.00 4123
condN:armND 0.01 0.00 -0.00 0.01 1.00 4184
patient1:condN:armND 0.00 0.01 -0.01 0.02 1.00 4076
sigma_condN -0.22 0.08 -0.37 -0.07 1.00 3463
sigma_armND 0.35 0.07 0.22 0.48 1.00 3723
sigma_condN:armND -0.60 0.10 -0.79 -0.41 1.00 3488
alpha_condN 2.44 0.74 1.08 3.97 1.00 4008
alpha_armND -1.23 0.88 -2.95 0.53 1.00 3828
alpha_condN:armND 0.58 1.07 -1.52 2.68 1.00 3629
Tail_ESS
sigma_Intercept 3138
alpha_Intercept 3245
Intercept 1453
patient1 2115
condN 1246
armND 1979
patient1:condN 3161
patient1:armND 2349
condN:armND 3428
patient1:condN:armND 2804
sigma_condN 2856
sigma_armND 2869
sigma_condN:armND 2478
alpha_condN 2856
alpha_armND 3053
alpha_condN:armND 2916
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
pp_check(m10_transFlat, nsamples = 100)
Fig. 25. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
beautify_my_plot(plot(conditional_effects(m10_transFlat,
dpar = "mu"),
plot = FALSE))
conditions <- make_conditions(drum_beats,
vars = "arm")
beautify_my_plot(plot(conditional_effects(m10_transFlat,
dpar = "mu",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m10_transFlat,
dpar = "sigma"),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m10_transFlat,
dpar = "sigma",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m10_transFlat,
dpar = "alpha"),
plot = FALSE))
beautify_my_plot(plot(conditional_effects(m10_transFlat,
dpar = "alpha",
effects = "patient:cond",
conditions = conditions),
plot = FALSE))
Fig. 26. Conditional plots. Had to take out all the fancy figure polishing, subplot lettering etc. Subplots are supposed to be numbered from A to … starting in the top left corner, proceeding row-wise.
In Fig. 26 the dots are the means of the posterior distributions of the respective estimate, and can be interpreted similarly to the point estimates in traditional frequentist statistics. The error bars represent 95% credible intervals, which are interpreted as comprising the true value with 95% probability, given the model and the data.
There is a difference in estimated the mean (‘mu’) of \(transSC\) conditional on group (A) and condition (B), not so on arm (C). Likewise, there is a two-way interaction between group and arm (D), but not between condition and arm (E). Consequently, there is no three-way interaction (F).
The remaining, unexplained variation ‘sigma’ shows a clear difference between instructions (H) and lesser so for side (I), but albeit their opposing trends, there is no interaction (J thru M).
There is a difference in estimated skewness (‘alpha’) both between instruction (O) and side (P), but with opposing trends. Nevertheless, there is no interaction between them (Q thru T).
From a data-driven perspective this should lead to a simplification of the model, leaving out all the unnecessary interaction terms. A theory-driven approach though requires the final model to be ‘full’ in the sense that all explanatory variables must interact with all others, implying that not finding an interaction between factors either is due to there really not being an interaction–rendering the model mis-specified and proving the underlying theory wrong–, or due to insufficient data. Since the data set at hand is very small I vote to blame the failure to find interactions between all factors on the small sample size and would therefore keep all interactions in the model.
wrap_plots(plot(conditional_effects(m10_transFlat,
dpar = "mu",
effects = "patient:cond",
conditions = conditions),
plot = FALSE)[[1]] +
scale_color_colorblind() +
theme(legend.position = "none"),
plot(conditional_effects(m10_transFlat,
dpar = "sigma",
effects = "patient:cond",
conditions = conditions),
plot = FALSE)[[1]] +
scale_color_colorblind() +
theme(legend.position = "none"),
plot(conditional_effects(m10_transFlat,
dpar = "alpha",
effects = "patient:cond",
conditions = conditions),
plot = FALSE)[[1]]) +
scale_color_colorblind() +
plot_annotation(tag_levels = "A")
Fig. 24. Three-way interaction plots of the three modeled parameters \(\mu\), \(\sigma\), and \(\alpha\) as estimated by the best-fitting model. The x axis shows group membership (0 = healthy subjects, 1 = patients). The instruction conditions are color-coded (black = controlled strokes, brown = normal strokes), and the facets show the side (1 = dominant, 2 = non-dominant).
transCrest(m10_transCrest_form <-bf(transCrest ~ 0 + Intercept + patient * cond * arm +
(1 | subj) +
(1 | cond) +
(1 | arm),
sigma ~ cond * arm,
alpha ~ cond * arm))
transCrest ~ 0 + Intercept + patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ cond * arm
alpha ~ cond * arm
(m10_transCrest_prior <- c(set_prior("normal(2.5, 10)", class = "b", coef = "Intercept"),
set_prior("normal(0, 10)", class = "b"),
set_prior("normal(0, 5)", class = "b", coef = "armND"),
set_prior("normal(0, 5)", class = "b", coef = "condN"),
set_prior("normal(0, 0.01)", class = "sd"),
set_prior("normal(0, 5)", class = "Intercept", dpar = "sigma"),
set_prior("normal(0, 5)", class = "b", dpar = "sigma"),
set_prior("normal(0, 2)", class = "Intercept", dpar = "alpha"),
set_prior("normal(0, 2)", class = "b", dpar = "alpha")
))
prior class coef group resp dpar nlpar bound source
normal(2.5, 10) b Intercept user
normal(0, 10) b user
normal(0, 5) b armND user
normal(0, 5) b condN user
normal(0, 0.01) sd user
normal(0, 5) Intercept sigma user
normal(0, 5) b sigma user
normal(0, 2) Intercept alpha user
normal(0, 2) b alpha user
if (MODEL) {
m10_transCrest <- brm(m10_transCrest_form,
prior = m10_transCrest_prior,
family = skew_normal(),
inits = "0",
control = list(max_treedepth = 15),
data = drum_beats)
m10_transCrest <- add_criterion(m10_transCrest,
"loo",
reloo = TRUE)
save(m10_transCrest,
file = "m10_transCrest.rda")
} else {
load("m10_transCrest.rda")
}
Tab. 15. Model summary.
(m10_transCrest_summary <- summary(m10_transCrest,
priors = TRUE))
Family: skew_normal
Links: mu = identity; sigma = log; alpha = identity
Formula: transCrest ~ 0 + Intercept + patient * cond * arm + (1 | subj) + (1 | cond) + (1 | arm)
sigma ~ cond * arm
alpha ~ cond * arm
Data: drum_beats (Number of observations: 1102)
Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 4000
Priors:
b ~ normal(0, 10)
b_armND ~ normal(0, 5)
b_condN ~ normal(0, 5)
b_Intercept ~ normal(2.5, 10)
b_alpha ~ normal(0, 2)
b_sigma ~ normal(0, 5)
Intercept_alpha ~ normal(0, 2)
Intercept_sigma ~ normal(0, 5)
sd ~ normal(0, 0.01)
Group-Level Effects:
~arm (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 0.01 0.01 0.00 0.02 1.00 3304 1997
~cond (Number of levels: 2)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 0.01 0.01 0.00 0.02 1.00 3684 2094
~subj (Number of levels: 8)
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
sd(Intercept) 0.09 0.01 0.08 0.10 1.00 3747 2329
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
sigma_Intercept -1.09 0.05 -1.19 -0.99 1.00 3410
alpha_Intercept 6.19 0.91 4.52 8.06 1.00 4994
Intercept 2.98 0.05 2.88 3.09 1.00 1796
patient1 -0.39 0.07 -0.53 -0.24 1.00 1796
condN -0.10 0.03 -0.17 -0.04 1.00 2963
armND -0.14 0.04 -0.22 -0.07 1.00 2394
patient1:condN -0.05 0.04 -0.13 0.03 1.00 3091
patient1:armND 0.18 0.05 0.09 0.27 1.00 2548
condN:armND 0.00 0.05 -0.09 0.10 1.00 2630
patient1:condN:armND 0.04 0.06 -0.08 0.16 1.00 2854
sigma_condN -0.48 0.07 -0.61 -0.34 1.00 3337
sigma_armND 0.19 0.07 0.06 0.32 1.00 3187
sigma_condN:armND 0.30 0.09 0.13 0.48 1.00 2909
alpha_condN -3.72 0.92 -5.66 -2.02 1.00 5054
alpha_armND 1.89 1.16 -0.36 4.21 1.00 4233
alpha_condN:armND 0.33 1.30 -2.21 2.88 1.00 3965
Tail_ESS
sigma_Intercept 3213
alpha_Intercept 2758
Intercept 2425
patient1 2258
condN 3242
armND 2726
patient1:condN 2864
patient1:armND 2879
condN:armND 3068
patient1:condN:armND 2865
sigma_condN 2867
sigma_armND 3116
sigma_condN:armND 2864
alpha_condN 2944
alpha_armND 3171
alpha_condN:armND 2933
Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
and Tail_ESS are effective sample size measures, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
pp_check(m10_transCrest, nsamples = 100)
Fig. 28. Posterior predictive check. The thick blue line shows the distribution of the empirical data. The thin blue lines are one-hundred realizations of data generated from parameters estimated by the model.
beautify_my_plot(plot(conditional_effects(m10_transCrest,
dpar = "mu"),
plot = FALSE))
conditions <- make_conditions(drum_beats,
vars = "arm")
conditional_effects(m10_transCrest,
dpar = "mu",
effects = "patient:cond",
conditions = conditions)
beautify_my_plot(plot(conditional_effects(m10_transCrest,
dpar = "sigma"),
plot = FALSE))
conditional_effects(m10_transCrest,
dpar = "sigma",
effects = "patient:cond",
conditions = conditions)
beautify_my_plot(plot(conditional_effects(m10_transCrest,
dpar = "alpha"),
plot = FALSE))
conditional_effects(m10_transCrest,
dpar = "alpha",
effects = "patient:cond",
conditions = conditions)
Fig. 29. Conditional plots. Had to take out all the fancy figure polishing, subplot lettering etc. Subplots are supposed to be numbered from A to … starting in the top left corner, proceeding row-wise.
In Fig. 29 the dots are the means of the posterior distributions of the respective estimate, and can be interpreted similarly to the point estimates in traditional frequentist statistics. The error bars represent 95% credible intervals, which are interpreted as comprising the true value with 95% probability, given the model and the data.
There is a difference in estimated the mean (‘mu’) of \(transSC\) conditional on group (A) and condition (B), not so on arm (C). Likewise, there is a two-way interaction between group and arm (D), but not between condition and arm (E). Consequently, there is no three-way interaction (F).
The remaining, unexplained variation ‘sigma’ shows a clear difference between instructions (H) and lesser so for side (I), but albeit their opposing trends, there is no interaction (J thru M).
There is a difference in estimated skewness (‘alpha’) both between instruction (O) and side (P), but with opposing trends. Nevertheless, there is no interaction between them (Q thru T).
From a data-driven perspective this should lead to a simplification of the model, leaving out all the unnecessary interaction terms. A theory-driven approach though requires the final model to be ‘full’ in the sense that all explanatory variables must interact with all others, implying that not finding an interaction between factors either is due to there really not being an interaction–rendering the model mis-specified and proving the underlying theory wrong–, or due to insufficient data. Since the data set at hand is very small I vote to blame the failure to find interactions between all factors on the small sample size and would therefore keep all interactions in the model.
wrap_plots(plot(conditional_effects(m10_transCrest,
dpar = "mu",
effects = "patient:cond",
conditions = conditions),
plot = FALSE)[[1]] +
scale_color_colorblind() +
theme(legend.position = "none"),
plot(conditional_effects(m10_transCrest,
dpar = "sigma",
effects = "patient:cond",
conditions = conditions),
plot = FALSE)[[1]] +
scale_color_colorblind() +
theme(legend.position = "none"),
plot(conditional_effects(m10_transCrest,
dpar = "alpha",
effects = "patient:cond",
conditions = conditions),
plot = FALSE)[[1]]) +
scale_color_colorblind() +
plot_annotation(tag_levels = "A")
Fig. 24. Three-way interaction plots of the three modeled parameters \(\mu\), \(\sigma\), and \(\alpha\) as estimated by the best-fitting model. The x axis shows group membership (0 = healthy subjects, 1 = patients). The instruction conditions are color-coded (black = controlled strokes, brown = normal strokes), and the facets show the side (1 = dominant, 2 = non-dominant).
Data wrangling and analyses were carried out with the statistical package R (R version 4.0.2 (2020-06-22); R Core Team 2020). Bayesian modeling was done with the package brms (Bürkner 2017, 2018) which uses the probabilistic language Stan as back end (Carpenter et al. 2017). Plots were done with the packages bayesplot (Gabry and Mahr 2020) and ggplot2 (Wickham 2016).
Bates, D. M. 2010. Lme4: Mixed-Effects Modeling with R. Springer. http://lme4.r-forge.r-project.org/lMMwR/lrgprt.pdf.
Bürkner, Paul-Christian. 2017. “Brms: An R Package for Bayesian Multilevel Models Using Stan.” Journal of Statistical Software 80 (1). https://doi.org/10.18637/jss.v080.i01.
———. 2018. “Advanced Bayesian Multilevel Modeling with the R Package Brms.” The R Journal 10 (1).
Carpenter, Bob, Andrew Gelman, Matthew Hoffman, Daniel Lee, Ben Goodrich, Michael Betancourt, Marcus Brubaker, Jiqiang Guo, Peter Li, and Allen Riddell. 2017. “Stan: A Probabilistic Programming Language.” Journal of Statistical Software, Articles 76 (1): 1–32. https://doi.org/10.18637/jss.v076.i01.
Câmara, Guilherme Schmidt, Kristian Nymoen, Olivier Lartillot, and Anne Danielsen. 2020. “Effects of Instructed Timing on Electric Guitar and Bass Sound in Groove Performance.” The Journal of the Acoustical Society of America 147 (2): 1028–41. https://doi.org/10.1121/10.0000724.
Danielsen, Anne, Carl Haakon Waadeland, Henrik G. Sundt, and Maria A. G. Witek. 2015. “Effects of Instructed Timing and Tempo on Snare Drum Sound in Drum Kit Performance.” The Journal of the Acoustical Society of America 138 (4): 2301–16. https://doi.org/10.1121/1.4930950.
Gabry, Jonah, and Tristan Mahr. 2020. “Bayesplot: Plotting for Bayesian Models.” https://mc-stan.org/bayesplot.
R Core Team. 2020. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.
Tibshirani, Robert. 1996. “Regression Shrinkage and Selection via the Lasso.” Journal of the Royal Statistical Society: Series B (Methodological) 58 (1): 267–88. https://doi.org/10.1111/j.2517-6161.1996.tb02080.x.
Wickham, Hadley. 2016. Ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. https://ggplot2.tidyverse.org.
Wilkinson, G. N., and C. E. Rogers. 1973. “Symbolic Description of Factorial Models for Analysis of Variance.” Applied Statistics 22 (3): 392–99. https://doi.org/10.2307/2346786.